package com.iwithlong.filter;


import com.imesne.assistant.common.utils.PropertyUtils;
import com.iwithlong.filter.exceptions.ForwardException;
import com.iwithlong.filter.handler.ForwardHandler;
import com.iwithlong.filter.http.RequestInfo;
import com.iwithlong.filter.http.ResponseInfo;
import com.iwithlong.filter.utils.ForwardHttpUtils;
import com.iwithlong.filter.utils.SessionUtils;
import com.ktanx.platform.web.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by liyingdan on 2017/1/4.
 */
@Slf4j
public class ForwardFilter implements Filter {

    private static final Logger LOG = LoggerFactory.getLogger(ForwardFilter.class);

    protected static final String KEY_PREFIX = "forward.handler.";

    /***
     * 默认的requestInfo构建器key
     */
    private static final String DEFAULT_FORWARD_HANDLER = "_default_forward_handler";

    private static final String[] INCLUDE_RESOURCES = {".js", ".css", ".gif", ".png", ".jpg", ".woff", ".ttf", ".svg", "op=h5_file_version"};

    /**
     * 代理处理器
     */
    private final Map<String, ForwardHandler> forwardHandlerMap = new HashMap<>();

    public static Object newInstance(String clazz, String ForwardName) {
        try {
            Class e = Thread.currentThread().getContextClassLoader().loadClass(clazz);
            Constructor constructor = e.getDeclaredConstructor(new Class[]{String.class});
            constructor.setAccessible(true);
            return constructor.newInstance(ForwardName);
        } catch (Exception var2) {
            throw new ForwardException("", "根据class创建实例失败:" + clazz, var2);
        }
    }

    public void init(FilterConfig config) throws ServletException {
        Map<String, String> properties = PropertyUtils.getProperties("forward.properties");
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            String forwardName = entry.getKey();
            if (!StringUtils.startsWith(forwardName, KEY_PREFIX)) {
                continue;
            }
            String key = StringUtils.substring(forwardName, KEY_PREFIX.length());
            forwardHandlerMap.put(key, (ForwardHandler ) newInstance(entry.getValue().trim(), key));
        }
    }


    protected String getForwardName(String requestURI) {
        int index = StringUtils.indexOf(requestURI, "/", 1);
        String forwardPath = StringUtils.substring(requestURI, 0, index);
        if (!StringUtils.equals("/proxy", forwardPath)) {
            return "default" ;
        }
        int i = requestURI.length();
        String forwardName = StringUtils.substring(requestURI, forwardPath.length() + 1, i);
        return forwardName;
    }

    /**
     * 获取代理处理器
     *
     * @param forwardName
     * @return
     */
    protected ForwardHandler getForwardHandler( String forwardName) {

        ForwardHandler forwardHandler = forwardHandlerMap.get(forwardName);
        if (forwardHandler == null) {
            forwardHandler = forwardHandlerMap.get(DEFAULT_FORWARD_HANDLER);
        }
        return forwardHandler;
    }

    protected void writeError(String errCode, String errMsg, HttpServletResponse response) {
        try {
            String json = String.format("{'errorCode':'%s','message':'%s'}", errCode, errMsg).replace(",", "\"");
            response.getWriter().print(json);
        } catch (IOException e) {
            LOG.warn("输出错误信息失败:", e);
            //ignore
        }
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String requestURI = ForwardHttpUtils.getRequestURI(request);
        String forwardName = this.getForwardName(requestURI);
        ForwardHandler forwardHandler = this.getForwardHandler(forwardName);
        if (forwardHandler==null) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {

            RequestInfo requestInfo = forwardHandler.buildForwardRequestInfo(request);

            if(!forwardHandler.isFilter(requestInfo,request) ){
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
//            String forwardUrl = StringUtils.substring(requestURI, forwardName.length() + 7);
            Map<String,String> params = ForwardHttpUtils.getParams(request);
            String forwardUrl = params == null ? null:params.get("url");
            if(StringUtils.isBlank(forwardUrl)){
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
            if (!forwardHandler.isValid(requestURI, request)) {
                throw new ForwardException ("403", "没有访问权限");
            }

            log.info("转发路径："+forwardUrl);
            ResponseInfo responseInfo = forwardHandler.requestTargetServer(requestInfo, forwardUrl, request);

            boolean isChain = forwardHandler.writeResponse(responseInfo, request, response);

            //返回true，继续往下走
            if (isChain) {
                filterChain.doFilter(servletRequest, servletResponse);
            }
        }
    }

    /**
     * 是否是不需要权限控制的资源
     *
     * @param requestUrl
     * @return
     */
    private boolean isIncludeResource(String requestUrl) {
        for (String resource : INCLUDE_RESOURCES) {
            if (StringUtils.indexOfIgnoreCase(requestUrl, resource) != -1) {
                return true;
            }
        }
        return false;
    }

    public void destroy() {

    }
}
